package com.societyGames.codeAlong.user
{
import com.societyGames.persist.IPersist;
import com.societyGames.utility.BitPacker;
import com.societyGames.utility.GUID;

import flash.events.EventDispatcher;

public class UserData extends EventDispatcher
{
  public static const MAJOR_VERSION:int = 1; //Incompatible versions.
  public static const MINOR_VERSION:int = 1; //Compatible version.

  private static const GENERIC_USER_ID:String = "00000000-0000-0000-0000-000000000000";

  private var _majorVersion:int; //The version of the save data
  private var _minorVersion:int; //The version of the save data

  protected var _userId:String;         //The unique identifier of this user.
  private var _currentExerciseId:uint; 		        //The exercise to load.
  private var _currentCode:String;			          //The code of the player's last state.
  private var _completedExerciseIds:BitPacker = new BitPacker(); 		//The exercises that have been completed

  protected var _userDataError:UserDataError = UserDataError.SUCCESS;

  public function UserData()
  {
    useDefaults();
  }

  private function useDefaults():void
  {
    this._majorVersion = MAJOR_VERSION;
    this._minorVersion = MINOR_VERSION;

    useGenericUserId();
    this._currentExerciseId = 0;
    this._currentCode = null;
    this._completedExerciseIds.clear();
  }

  public function serialize(persist:IPersist):void
  {
    persist.setData("major", this._majorVersion);
    persist.setData("minor", this._minorVersion);

    persist.setData("userId", this._userId);
    persist.setData("exerciseId", this._currentExerciseId);
    persist.setData("code", this._currentCode);
    persist.setData("completed", this._completedExerciseIds.packedValues);

    this._userDataError = UserDataError.SUCCESS;
  }

  public function deserialize(persist:IPersist):UserDataError
  {
    _userDataError = UserDataError.SUCCESS;
    try
    {
      var oldMajorVersion:int = int(persist.getData("major"));
      var oldMinorVersion:int = int(persist.getData("minor"));
      if (oldMajorVersion > 0 || oldMinorVersion > 0) //We have data
      {
        if (oldMajorVersion == 0) //The data is incompatible
        {
          _userDataError = UserDataError.INCOMPATIBLE_VERSION;
        }
        else if (oldMajorVersion < UserData.MAJOR_VERSION)
        {
          //TODO: Try to get the UserID even if we can't recover anything else
          _userDataError = UserDataError.INCOMPATIBLE_VERSION;
        }
        else //Data is correct version.
        {
          readFromPersist(persist);
        }
      }
      else
      {
        _userDataError = UserDataError.EMPTY;
      }
    }
    catch (error:Error)
    {
      _userDataError = UserDataError.CORRUPT;
    }
    /*if (this._userDataError != UserDataError.SUCCESS)
     {
     useDefaults();
     }*/
    return this._userDataError;
  }

  private function readFromPersist(persist:IPersist):void
  {
    var tempObject:Object;

    if ((tempObject = persist.getData("userId")) != null)
    {
      this._userId = String(tempObject);
    }

    if ((tempObject = persist.getData("exerciseId")) != null)
    {
      this._currentExerciseId = uint(tempObject);
    }

    if ((tempObject = persist.getData("code")) != null)
    {
      this._currentCode = String(tempObject);
    }

    if ((tempObject = persist.getData("completed")) != null)
    {
      this._completedExerciseIds.packedValues = tempObject as Vector.<uint>;
    }
  }

  protected function useUniqueUserID():void
  {
    this._userId = GUID.create();
  }

  protected function useGenericUserId():void
  {
    //BE32B076-4C84-1C09-E3D4-931476DDE18C
    //00000000-0000-0000-0000-000000000000
    this._userId = GENERIC_USER_ID;
  }

  protected function isUserIdGeneric():Boolean
  {
    return this._userId == GENERIC_USER_ID;
  }

  public function get userId():String
  {
    return this._userId;
  }

  public function get currentExerciseId():uint
  {
    return this._currentExerciseId;
  }

  public function set currentExerciseId(value:uint):void
  {
    this._currentExerciseId = value;
  }

  public function get currentCode():String
  {
    return this._currentCode;
  }

  public function set currentCode(value:String):void
  {
    this._currentCode = value;
  }

  public function get completedExerciseIds():BitPacker
  {
    return _completedExerciseIds;
  }

  public function get userDataError():UserDataError
  {
    return _userDataError;
  }
}
}

/*
 0.1  - Old Spaced Out Numbering, No Completed List.
 private var _majorVersion:int; //The version of the save data
 private var _minorVersion:int; //The version of the save data

 private var _currentExerciseId:uint; 		//The exercise to load.
 private var _currentCode:String;			//The code of the player's last state.*/
